// 路径包
const path = require('path')
// 添加html-loader
const HtmlWebpackPlugin = require('html-webpack-plugin')
// css处理
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// 直接打包复制文件夹
const CopyPlugin = require('copy-webpack-plugin')
// 导入webpack5
const webpack = require('webpack')
// vue加载插件
const { VueLoaderPlugin } = require('vue-loader')
// 是否是生产模式
const isProd = process.env.NODE_ENV === 'production'
// 打包进度条
const WebpackBar = require('webpackbar')
// 处理eslint
const ESLintPlugin = require('eslint-webpack-plugin')

module.exports = {
  mode: isProd ? 'production' : 'development',
  target: 'web',
  stats: 'errors-only',
  entry: {
    app: {
      import: './src/main.ts'
    }
  },
  // 输出位置
  output: {
    path: path.resolve(process.cwd(), 'dist'),
    filename: 'assets/js/[name].js',
    chunkFilename: 'assets/js/vendor.[chunkhash:8].js'
  },
  resolve: {
    extensions: ['.js', '.jsx', '.json', '.ts', 'tsx', '.scss', '.sass']
  },
  module: {
    rules: [
      // 处理文件
      {
        test: /\.(png|jpg|gif|svg|zip|gz|rar|woff2|woff|eot|ttf|otf)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
              outputPath: (name) => {
                const paths = [
                  ['assets/images', /(png|jpg|gif|svg)/],
                  ['assets/zip', /(zip|gz|rar)/],
                  ['assets/fonts', /(woff2|woff|eot|ttf|otf)/]
                ]
                // 默认的返回名称
                let result = path.join('assets', name)
                const tmp = name.split('.')
                const ext = tmp[tmp.length - 1]
                for (const item of paths) {
                  if (item[1].test(ext)) {
                    result = path.join(item[0], name)
                    break
                  }
                }
                // 将windows路径转为标准linux路径
                return result.replace(/\\/g, '/')
              },
              esModule: false
            }
          }
        ]
      },
      // 处理vue
      {
        test: /.vue$/,
        use: [
          {
            loader: 'vue-loader'
          }
        ]
      },
      // script 处理
      {
        test: /\.(ts|js|tsx|jsx)$/,
        use: [
          {
            loader: 'esbuild-loader',
            options: {
              loader: 'ts'
            }
          }
        ]
      },
      // css 和 scss 处理
      {
        test: /\.(css|scss|sass)$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader
          },
          {
            loader: 'css-loader',
            options: {
              esModule: false
            }
          },
          {
            loader: 'sass-loader'
          }
        ]
      }
    ]
  },
  optimization: {
    splitChunks: {
      minSize: 80000,
      maxSize: 400000,
      minChunks: 1,
      automaticNameDelimiter: '.',
      hidePathInfo: true,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          name: 'module',
          chunks: 'all'
        }
      }
    }
  },
  plugins: [
    // 加载vue
    new VueLoaderPlugin(),
    // 处理eslint
    new ESLintPlugin({
      extensions: ['js','jsx','ts','tsx','vue']
    }),
    // 渲染html
    new HtmlWebpackPlugin({
      template: './src/public/index.html',
      inject: 'body',
      chunks: ['app']
    }),
    // css分离处理
    new MiniCssExtractPlugin({
      filename: 'assets/css/[name].css',
      chunkFilename: 'assets/css/vendor.[chunkhash:8].css'
    }),
    // 将public的内容复制到打包目录
    new CopyPlugin({
      patterns: [
        {
          from: './src/public',
          to: './',
          filter (filePath) {
            const filterItems = [
              /src\/public\/index.html$/ // 排除index.html
            ].filter((val) => {
              if (val.test(filePath)) return true
              return false
            })
            return filterItems.length == 0
          }
        }
      ]
    }),
    // 提供变量
    new webpack.DefinePlugin({
      IS_RENDERED: false
    }),
    // 打包进度条
    new WebpackBar({
      name: 'Client',
      color: 'blue'
    })
  ],
  devtool: isProd ? false : 'source-map'
}
